/**
 * @file main.c
 * @author zhao yijing
 * @brief  main
 * @version 0.1
 * @date 2022-11-03
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "xdisk.h"
#include "stdio.h"
#include "driver.h"
#include "xfat.h"

#include "stdlib.h"
#include "string.h"

uint8_t wr_buf[1024] = {0};
uint8_t rd_buf[1024] = {0};
const char *path_test_io = "disk_test.img";
const char *path_test_fat = "./disk.img";
int xdisk_io_test(void);         // disk层读写接口测试
int xdisk_part_count_test(void); // disk层解析分区数接口测试
int xdisk_part_info_test(void);  // disk层解析分区信息
int xfat_dir_file_test(void);    // fat层解析根目录 打印文件内容
int xfat_file_test(void);        // fat层文件操作

int main(int argc, char const *argv[])
{
    int err = 0;
    err = xfat_dir_file_test();
    if (err < 0)
    {
        printf("fat root dir test failed\n");
        return -1;
    }
    printf("fat root dir test succ\n");

    return 0;
}

int xdisk_io_test(void)
{
    xdisk_t disk_test = {0};
    xdisk_driver_t *v_disk_driver = NULL;
    xfat_err_t err = 0;

    v_disk_driver = get_vdisk_drv();

    // 打开磁盘
    err = xdisk_open(&disk_test, "vdisk_test", v_disk_driver, (void *)path_test_io);
    if (err != FS_ERR_OK)
    {
        printf("xdisk open failed\n");
        return -1;
    }

    for (int i = 0; i < sizeof(wr_buf); i++)
    {
        wr_buf[i] = 0;
    }

    // 测试读写扇区接口
    err = xdisk_write_sector(&disk_test, wr_buf, 0, 2);
    if (err != FS_ERR_OK)
    {
        printf("xdisk write failed\n");
        return -1;
    }

    err = xdisk_read_sector(&disk_test, rd_buf, 0, 2);
    if (err != FS_ERR_OK)
    {
        printf("xdisk read failed\n");
        return -1;
    }
    for (int i = 0; i < sizeof(rd_buf); i++)
    {
        if (wr_buf[i] != rd_buf[i])
        {
            printf("file wr/rd err\n");
            return -1;
        }
    }

    // 关闭磁盘
    err = xdisk_close(&disk_test);
    if (err != FS_ERR_OK)
    {
        printf("xdisk close failed\n");
        return -1;
    }
    return 0;
}

int xdisk_part_count_test(void)
{
    xdisk_t disk_test = {0};
    xdisk_driver_t *v_disk_driver = NULL;
    xfat_err_t err = 0;
    uint32_t main_part_count = 0;

    v_disk_driver = get_vdisk_drv();

    // 打开磁盘
    err = xdisk_open(&disk_test, "vdisk_test", v_disk_driver, (void *)path_test_fat);
    if (err != FS_ERR_OK)
    {
        printf("xdisk open failed\n");
        return -1;
    }

    // 获取分区数量
    err = xdisk_get_part_count(&disk_test, &main_part_count);
    if (err < 0)
    {
        xdisk_close(&disk_test);
        return err;
    }

    printf("get part count %d\n", main_part_count);

    xdisk_close(&disk_test);
}

int xdisk_part_info_test(void)
{
    xdisk_t disk_test = {0};
    xdisk_part_t disk_part_test = {0};
    xdisk_driver_t *v_disk_driver = NULL;
    xfat_err_t err = 0;
    uint32_t part_count = 0;

    v_disk_driver = get_vdisk_drv();

    // 打开磁盘
    err = xdisk_open(&disk_test, "vdisk_test", v_disk_driver, (void *)path_test_fat);
    if (err != FS_ERR_OK)
    {
        printf("xdisk open failed\n");
        return -1;
    }

    // 获取磁盘上分区数量 主分区 + 扩展分区
    err = xdisk_get_part_count(&disk_test, &part_count);
    if (err < 0)
    {
        printf("xdisk get part count failed %d\n", err);
        xdisk_close(&disk_test);
        return err;
    }

    printf("disk part %d\n", part_count);

    // 循环打印磁盘信息 通过磁盘的MBR
    for (int i = 0; i < part_count; i++)
    {
        err = xdisk_get_part(&disk_test,
                             &disk_part_test,
                             i);
        if (err < 0)
        {
            printf("xdisk get part info failed %d\n", err);
            xdisk_close(&disk_test);
            return err;
        }
        printf("no\t%d\t|start\t%d|count\t%d|capacity\t%0.f M\n",
               i,
               disk_part_test.start_sector,
               disk_part_test.total_sector,
               disk_part_test.total_sector * disk_test.sector_size / 1024 / 1024.0);
    }

    xdisk_close(&disk_test);
    return 0;
}

int xfat_dir_file_test(void)
{
    xdisk_t disk_test = {0};           // disk
    xdisk_part_t disk_part_test = {0}; // part
    xfat_t fat_test = {0};             // fat

    xdisk_driver_t *v_disk_driver = NULL; // 虚拟磁盘驱动
    xfat_err_t err = FS_ERR_OK;

    uint32_t root_dir_cluster_num;  // 根目录所在簇号
    uint8_t *rd_cluster_buf = NULL; // 簇缓冲区

    dir_item_t *dir_item = NULL;  // 目录项指针
    uint8_t *item_name = NULL;    // 目录项名称
    char item_name_buf[12] = {0}; // 目录项名成缓冲区
    uint32_t item_index = 0;      // 目录项计数

    uint32_t file_takeup_size = 0; // 文件实际占用的字节数

    v_disk_driver = get_vdisk_drv();

    // 打开磁盘
    err = xdisk_open(&disk_test, "vdisk", v_disk_driver, (void *)path_test_fat);
    if (err < 0)
    {
        printf("open disk failed\n");
        return -1;
    }

    // 获取磁盘指定分区 获取1号分区的分区
    err = xdisk_get_part(&disk_test, &disk_part_test, 1);
    if (err < 0)
    {
        printf("get disk part info failed\n");
        xdisk_close(&disk_test);
        return -1;
    }

    // 通过FAT格式解析该分区
    err = xfat_open(&fat_test, &disk_part_test);
    if (err < 0)
    {
        printf("fat open failed\n");
        xdisk_close(&disk_test);
        return -1;
    }

    printf("dir test ready...\n");

    root_dir_cluster_num = fat_test.root_cluster;
    rd_cluster_buf = malloc(fat_test.cluster_byte_size);

    // 解析根目录
    if (rd_cluster_buf != NULL)
    {
        printf("no\tname\t\tattr\tstart_cluster_no\n");
        while (is_cluster_valid(root_dir_cluster_num) == 1)
        {
            err = read_cluster(&fat_test, rd_cluster_buf, root_dir_cluster_num, 1);
            if (err < 0)
            {
                printf("read cluster failed\n");
                free(fat_test.fat_tbl_buf);
                xdisk_close(&disk_test);
                return -1;
            }

            dir_item = (dir_item_t *)rd_cluster_buf;

            // 循环打印根目录下的所有文件
            for (int i = 0; i < (fat_test.cluster_byte_size / sizeof(dir_item_t)); i++)
            {
                item_name = dir_item[i].dir_name;
                if (item_name[0] == DIRITEM_NAME_FREE)
                {
                    // 空目录项 跳过
                    continue;
                }
                else if (item_name[0] == DIRITEM_NAME_END)
                {
                    // 目录项结束标志 跳出
                    break;
                }

                item_index++;
                memset(item_name_buf, 0x00, 12);
                memcpy(item_name_buf, dir_item[i].dir_name, 11);
                if (item_name_buf[0] == 0x05)
                {
                    item_name_buf[0] = 0xE5;
                }
                printf("%d\t%s\t0x%02x\t%d\n",
                       item_index,
                       item_name_buf,
                       dir_item[i].dir_atr,
                       ((dir_item[i].dir_fst_clus_hi << 16) | (dir_item[i].dir_fst_clus_lo)));
            }

            err = get_next_cluster(&fat_test,
                                   root_dir_cluster_num,
                                   &root_dir_cluster_num);
            if (err < 0)
            {
                printf("get next cluster failed\n");
                free(fat_test.fat_tbl_buf);
                return -1;
            }
        }
    }
    else
    {
        printf("malloc cluster buf failed\n");
        free(fat_test.fat_tbl_buf);
        xdisk_close(&disk_test);
        return -1;
    }

    free(rd_cluster_buf);

    // 读文件内容
    printf("file test ready...\n");
    root_dir_cluster_num = 4565;
    rd_cluster_buf = malloc(fat_test.cluster_byte_size + 1);
    if (rd_cluster_buf != NULL)
    {
        while (is_cluster_valid(root_dir_cluster_num) == 1)
        {
            err = read_cluster(&fat_test,
                               rd_cluster_buf,
                               root_dir_cluster_num,
                               1);
            if (err < 0)
            {
                printf("read cluster failed\n");
                free(fat_test.fat_tbl_buf);
                xdisk_close(&disk_test);
                free(rd_cluster_buf);
                return -1;
            }

            rd_cluster_buf[fat_test.cluster_byte_size + 1] = '\0';
            printf("%s", rd_cluster_buf);

            file_takeup_size += fat_test.cluster_byte_size;
            err = get_next_cluster(&fat_test,
                                   root_dir_cluster_num,
                                   &root_dir_cluster_num);
            if (err < 0)
            {
                printf("get next cluster failed\n");
                free(fat_test.fat_tbl_buf);
                xdisk_close(&disk_test);
                free(rd_cluster_buf);
                return -1;
            }
        }
        printf("\nfile take up size %d\n", file_takeup_size);
    }

    free(rd_cluster_buf);
    free(fat_test.fat_tbl_buf);
    xdisk_close(&disk_test);
    return 0;
}

int xfat_file_test(void)
{
    xfat_err_t err = FS_ERR_OK;
    xfile_t file = {0};
    xfat_t xfat = {0};

    err = xfile_open(&xfat, &file, "/");
    if (err != FS_ERR_OK)
    {
        printf("open file failed\n");
        return -1;
    }
    xfile_close(&file);

    return 0;
}
